// Package registry
// Title 			consul.registry.components.go
// Description 		Consul 注册中心工厂, 实现 factory.ApplicationRegistryLoaderFactory, 实现其远程加载器接口方法
// Author  			alittlexincan@163.com 					2024/07/22 11:36
// Update  			alittlexincan@163.com 					2024/07/22 11:36
package registry

import (
	"fmt"
	"strconv"

	"github.com/hashicorp/consul/api"
	"go.uber.org/zap"
	"xincan.com.cn/tarot-go/internal/common/constants"
	"xincan.com.cn/tarot-go/internal/config/factory"
	"xincan.com.cn/tarot-go/internal/utils"
)

// consulRegistryComponent
// Title 			consulRegistryComponent
// Description 		Consul 注册中心结构体
// Author  			alittlexincan@163.com 					2024/07/22 11:36
// Update  			alittlexincan@163.com 					2024/07/22 11:36
type consulRegistryComponent struct {
	factory.BaseConfigLoader[factory.ApplicationRegistryLoaderFactory]        // 基础配置加载器, 内置全局配置和日志
	*service                                                                  // 服务信息
	IP                                                                 string `mapstructure:"ip" json:"ip"`                                                         // 注册中心IP
	Port                                                               int    `mapstructure:"port" json:"port"`                                                     // 注册中心端口
	Interval                                                           string `mapstructure:"interval" json:"interval"`                                             // 轮询间隔
	Timeout                                                            string `mapstructure:"timeout" json:"timeout"`                                               // 连接超时
	DeregisterCriticalServiceAfter                                     string `mapstructure:"deregisterCriticalServiceAfter" json:"deregisterCriticalServiceAfter"` // 注销服务时间

}

// ConfigLoad
// Title 			ConfigLoad
// Description 		实现 factory.ApplicationRegistryLoaderFactory 接口方法, 获取 Consul 注册中心配置信息
// Author  			alittlexincan@163.com 										2024/07/22 11:36
// Update  			alittlexincan@163.com 										2024/07/22 11:36
// Return    		factory.ApplicationRegistryLoaderFactory 					返回注册中心工厂实例
func (consul *consulRegistryComponent) ConfigLoad() (interface{}, factory.ApplicationRegistryLoaderFactory) {

	consul.service = &service{
		address: consul.App.Config.Ip,
		port:    consul.App.Config.Port,
		name:    consul.App.Config.Name,
		logPath: consul.App.Config.Log.Path,
	}

	logger := consul.Logger.Logger
	// 1. 初始化Consul客户端
	config := api.DefaultConfig()
	config.Address = fmt.Sprintf("%s:%d", consul.IP, consul.Port)
	client, err := api.NewClient(config)
	if err != nil {
		logger.Error("Consul初始化失败", zap.Error(err))
	}
	// 2. 构造注册信息
	registration := &api.AgentServiceRegistration{
		ID:      utils.GetHostName() + "::" + strconv.Itoa(consul.service.port) + "::" + consul.service.name,
		Name:    consul.service.name,
		Address: consul.service.address,
		Port:    consul.service.port,
		Tags:    []string{"primary", "v1"},
		Check: &api.AgentServiceCheck{
			HTTP:                           fmt.Sprintf("http://%s:%d%s", consul.service.address, consul.service.port, "/health"),
			Interval:                       consul.Interval,                       // 轮询间隔
			Timeout:                        consul.Timeout,                        // 连接超时
			DeregisterCriticalServiceAfter: consul.DeregisterCriticalServiceAfter, // 故障后自动注销
		},
	}

	// 3. 执行注册
	if err := client.Agent().ServiceRegister(registration); err != nil {
		logger.Error("应用服务注册失败", zap.Error(err))
	}
	logger.Info("当前服务注册成功")
	return client, consul
}

// init
// Title 			init
// Description 		初始化时自动实例化自身实例, 并在main包中导入当前包路径
// Author      		alittlexincan@163.com       			2024/07/17 11:36
// Update    		alittlexincan@163.com       			2024/07/17 11:36
func init() {
	factory.RegisterCenterFactory(constants.ProviderRegistryConsul, &consulRegistryComponent{})
}
